package com.egene.tw.activity.signs.sleep;

import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import com.egene.tw.R;
import com.egene.tw.activity.signs.BarChartData;
import com.egene.tw.activity.signs.BarChartItemData;
import com.egene.tw.activity.signs.BaseMeasureActivity;
import com.egene.tw.bus.BusHelper;
import com.egene.tw.bus.LoadDataEndEvent;
import com.egene.tw.data.DataRepository;
import com.egene.tw.data.utils.DateFormUtils;
import com.egene.tw.data.entity.SleepData;
import com.egene.tw.ui.signs.SleepCenterView;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;
import org.greenrobot.eventbus.Subscribe;

import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

@EActivity(R.layout.activity_sleep)
public class SleepActivity extends BaseMeasureActivity {
    float MAX_VALUE = 100;

    enum DateType {
        day, week, month
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BusHelper.register(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        BusHelper.unRegister(this);
    }

    @ViewById(R.id.viewCenter)
    SleepCenterView viewCenter;

    //ToolBar Views
    @ViewById(R.id.actionBar)
    Toolbar mToolbarView;
    @ViewById(R.id.toolbar_title)
    TextView mToolBarTitle;


    @ViewById(R.id.viewTop)
    View viewTop;
    @ViewById(R.id.viewChart)
    View viewChart;
    @ViewById(R.id.barChart)
    BarChart mChart;
    @ViewById(R.id.viewDay)
    TextView viewDay;
    @ViewById(R.id.viewWeek)
    TextView viewWeek;
    @ViewById(R.id.viewMonth)
    TextView viewMonth;

    @ViewById(R.id.textDateTitle)
    TextView textDateTitle;
    @ViewById(R.id.textLastTime)
    TextView textLastTime;


    @ViewById(R.id.textDay1)
    TextView textDay1;
    @ViewById(R.id.textDay2)
    TextView textDay2;
    @ViewById(R.id.textDay3)
    TextView textDay3;


    @ViewById(R.id.textLeftP)
    TextView textLeftP;
    @ViewById(R.id.textRightP)
    TextView textRightP;
    @ViewById(R.id.textSleepHour)
    TextView textSleepHour;
    @ViewById(R.id.textSleepMin)
    TextView textSleepMin;

    @ViewById(R.id.textSleepHour1)
    TextView textSleepHour1;
    @ViewById(R.id.textSleepMin1)
    TextView textSleepMin1;
    @ViewById(R.id.textDeepHour)
    TextView textDeepHour;
    @ViewById(R.id.textDeepMin)
    TextView textDeepMin;
    @ViewById(R.id.textShallowHour)
    TextView textShallowHour;
    @ViewById(R.id.textShallowMin)
    TextView textShallowMin;
    @ViewById(R.id.textWlakup)
    TextView textWlakup;


    private BarChartData barChartData;
    private long time = System.currentTimeMillis();
    private DateType dateType = DateType.day;


    @AfterViews
    void init() {
        mToolbarView.setNavigationIcon(R.drawable.ic_back);
        mToolbarView.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        initBle();

        day();
    }

    @Click(R.id.viewDay)
    void day() {
        viewTop.setVisibility(View.VISIBLE);
        viewChart.setVisibility(View.GONE);
        textLastTime.setVisibility(View.VISIBLE);

        viewDay.setBackgroundResource(R.drawable.date_bottom_bg);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg_1);

        viewDay.setTextColor(getResources().getColor(R.color.colorWhite));
        viewWeek.setTextColor(getResources().getColor(R.color.colorText));
        viewMonth.setTextColor(getResources().getColor(R.color.colorText));


        time = System.currentTimeMillis();
        dateType = DateType.day;
        loadDayData();
        updateUI();
    }

    @Click(R.id.viewWeek)
    void week() {
        viewTop.setVisibility(View.GONE);
        viewChart.setVisibility(View.VISIBLE);
        textLastTime.setVisibility(View.GONE);

        viewDay.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg_1);

        viewDay.setTextColor(getResources().getColor(R.color.colorText));
        viewWeek.setTextColor(getResources().getColor(R.color.colorWhite));
        viewMonth.setTextColor(getResources().getColor(R.color.colorText));


        time = System.currentTimeMillis();
        dateType = DateType.week;
        loadWeekData();
        updateUI();

    }

    @Click(R.id.viewMonth)
    void month() {
        viewTop.setVisibility(View.GONE);
        viewChart.setVisibility(View.VISIBLE);
        textLastTime.setVisibility(View.GONE);

        viewDay.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewWeek.setBackgroundResource(R.drawable.date_bottom_bg_1);
        viewMonth.setBackgroundResource(R.drawable.date_bottom_bg);

        viewDay.setTextColor(getResources().getColor(R.color.colorText));
        viewWeek.setTextColor(getResources().getColor(R.color.colorText));
        viewMonth.setTextColor(getResources().getColor(R.color.colorWhite));

        time = System.currentTimeMillis();
        dateType = DateType.month;
        loadMonthData();
        updateUI();
    }

    @Click(R.id.textDay1)
    void textDay1() {
        switch (dateType) {
            case day:
                if (DateFormUtils.isToday(time)) {
                    time -= DateFormUtils.DAY * 2;
                } else {
                    time -= DateFormUtils.DAY;
                }
                loadDayData();
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    time -= DateFormUtils.DAY * 7 * 2;
                } else {
                    time -= DateFormUtils.DAY * 7;
                }
                loadWeekData();
                break;
            case month:
                if (DateFormUtils.isToMonth(time)) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -2);
                    time = calendar.getTime().getTime();
                } else {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -1);
                    time = calendar.getTime().getTime();
                }
                loadMonthData();
                break;
        }
        updateUI();
    }

    @Click(R.id.textDay2)
    void textDay2() {
        switch (dateType) {
            case day:
                if (!DateFormUtils.isToday(time)) {
                    return;
                }
                time -= DateFormUtils.DAY;
                loadDayData();
                break;
            case week:
                if (!DateFormUtils.isToWeek(time)) {
                    return;
                }
                time -= DateFormUtils.DAY * 7;
                loadWeekData();
                break;
            case month:
                if (!DateFormUtils.isToMonth(time)) {
                    return;
                }
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(time);
                calendar.add(Calendar.MONTH, -1);
                time = calendar.getTime().getTime();
                loadMonthData();
                break;
        }
        updateUI();
    }

    @Click(R.id.textDay3)
    void textDay3() {
        switch (dateType) {
            case day:
                if (DateFormUtils.isToday(time)) {
                    return;
                }
                time += DateFormUtils.DAY;
                loadDayData();
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    return;
                }
                time += DateFormUtils.DAY * 7;
                loadWeekData();
                break;
            case month:
                if (DateFormUtils.isToMonth(time)) {
                    return;
                }
                Calendar calendar = Calendar.getInstance();
                calendar.setTimeInMillis(time);
                calendar.add(Calendar.MONTH, 1);
                time = calendar.getTime().getTime();
                loadMonthData();
                break;
        }
        updateUI();
    }


    @Subscribe
    public void onEvent(LoadDataEndEvent data) {
        day();
    }


    public void adapterCommand(BarChartData chartData) {
        barChartData = chartData;
        mChart.setNoDataText(getString(R.string.no_data));
        if (barChartData == null || barChartData.getList() == null || barChartData.getList().size() == 0) {
            return;
        }
        mChart.setScaleEnabled(false);

        Typeface mTfLight = Typeface.createFromAsset(mChart.getContext().getAssets(), "OpenSans-Light.ttf");
        mChart.getDescription().setEnabled(false);

        // scaling can now only be done on x- and y-axis separately
        mChart.setPinchZoom(false);

        mChart.setDrawBarShadow(false);
        mChart.setDrawGridBackground(false);

        Legend l = mChart.getLegend();
        l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
        l.setOrientation(Legend.LegendOrientation.VERTICAL);
        l.setDrawInside(true);
        l.setTypeface(mTfLight);
        l.setYOffset(0f);
        l.setXOffset(10f);
        l.setYEntrySpace(0f);
        l.setTextSize(8f);
        l.setTextColor(Color.parseColor("#ffffff"));

        XAxis xAxis = mChart.getXAxis();
        xAxis.setTextColor(Color.parseColor("#ffffff"));
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setTypeface(mTfLight);
        xAxis.setDrawGridLines(false);
        xAxis.setGranularity(1f); // only intervals of 1 day
        xAxis.setLabelCount(7);

        xAxis.setValueFormatter(new IAxisValueFormatter() {
            @Override
            public String getFormattedValue(float value, AxisBase axis) {
                if (barChartData == null
                        || barChartData.getList() == null
                        || barChartData.getList().size() < (int) value) {
                    return "";
                }
                return barChartData.getList().get((int) value).getxDesc();
            }
        });

        YAxis leftAxis = mChart.getAxisLeft();
        leftAxis.setTypeface(mTfLight);
        leftAxis.setTextColor(Color.parseColor("#ffffff"));
        leftAxis.setDrawGridLines(false);
        leftAxis.setSpaceTop(35f);
        leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true)

        mChart.getAxisRight().setEnabled(false);

        //
        //------------
        //


        ArrayList<BarEntry> yVals1 = new ArrayList<BarEntry>();

        List<BarChartItemData> itemList = barChartData.getList();
        for (int i = 0; i < itemList.size(); i++) {
            BarChartItemData item = itemList.get(i);
            yVals1.add(new BarEntry(i, new float[]{item.getLow() / 60f, item.getHigh() / 60f}));
        }


        BarDataSet set1;

        if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) {
            set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0);
            set1.setValues(yVals1);
            mChart.getData().notifyDataChanged();
            mChart.notifyDataSetChanged();
            mChart.invalidate();
        } else {
            // create 4 DataSets
            set1 = new BarDataSet(yVals1, "");
            set1.setStackLabels(new String[]{getString(R.string.qiandu_sleep), getString(R.string.shendu_sleep)});

            set1.setColors(new int[]{Color.parseColor("#e38747"), Color.parseColor("#2515b7")});
            set1.setValueTextColor(Color.rgb(255, 255, 255));

            BarData data = new BarData(set1);
            data.setValueFormatter(new IValueFormatter() {
                @Override
                public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
                    if(value == 0){
                        return "";
                    }
                    return "" + (int) value;
                }
            });
            data.setValueTypeface(mTfLight);

            mChart.setData(data);
            mChart.invalidate();
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////
    private void loadDayData() {
        loadDayAnalysis();
        DataRepository.getInstance()
                .sleepBarDataByDay(time)
                .subscribe(new Observer<SleepData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(SleepData stepData) {
                        double lp = stepData.getTotal() == 0 ? 0 : stepData.getShallowValue() * 100.0 / stepData.getTotal();
                        double rp = stepData.getTotal() == 0 ? 0 : stepData.getDeepValue() * 100.0 / stepData.getTotal();

                        textLeftP.setText("" + Math.round(lp));
                        textRightP.setText("" + Math.round(rp));
                        textSleepHour.setText("" + (stepData.getTotal() / 60));
                        textSleepMin.setText("" + (stepData.getTotal() % 60));

                        viewCenter.setPercent(Math.round(rp));


                        if(stepData.getTime() != 0){
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            textLastTime.setText(getString(R.string.last_measure_time) + sdf.format(stepData.getTime()));
                        }else {
                            textLastTime.setText("");
                        }
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadWeekData() {
        loadWeelAnalysis();
        DataRepository.getInstance()
                .sleepBarDataByWeek(time)
                .subscribe(new Observer<BarChartData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BarChartData barChartData) {
                        adapterCommand(barChartData);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadMonthData() {
        loadMonthAnalysis();
        DataRepository.getInstance()
                .sleepBarDataByMonth(time)
                .subscribe(new Observer<BarChartData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BarChartData barChartData) {
                        adapterCommand(barChartData);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    ///////////////////////////////////////////////////////////////////////////
    //
    ///////////////////////////////////////////////////////////////////////////
    private void loadDayAnalysis() {
        DataRepository.getInstance()
                .sleepAnalysisByDay(time)
                .subscribe(new Observer<SleepData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(SleepData sleepData) {
                        textSleepHour1.setText("" + (sleepData.getTotal() / 60));
                        textSleepMin1.setText("" + (sleepData.getTotal() % 60));

                        textDeepHour.setText("" + (sleepData.getDeepValue() / 60));
                        textDeepMin.setText("" + (sleepData.getDeepValue() % 60));
                        textShallowHour.setText("" + (sleepData.getShallowValue() / 60));
                        textShallowMin.setText("" + (sleepData.getShallowValue() % 60));
                        textWlakup.setText("" + sleepData.getWalkingTimes());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadWeelAnalysis() {
        DataRepository.getInstance()
                .sleepAnalysisByWeek(time)
                .subscribe(new Observer<SleepData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(SleepData sleepData) {
                        textSleepHour1.setText("" + (sleepData.getTotal() / 60));
                        textSleepMin1.setText("" + (sleepData.getTotal() % 60));

                        textDeepHour.setText("" + (sleepData.getDeepValue() / 60));
                        textDeepMin.setText("" + (sleepData.getDeepValue() % 60));
                        textShallowHour.setText("" + (sleepData.getShallowValue() / 60));
                        textShallowMin.setText("" + (sleepData.getShallowValue() % 60));
                        textWlakup.setText("" + sleepData.getWalkingTimes());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private void loadMonthAnalysis() {
        DataRepository.getInstance()
                .sleepAnalysisByMonth(time)
                .subscribe(new Observer<SleepData>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(SleepData sleepData) {
                        textSleepHour1.setText("" + (sleepData.getTotal() / 60));
                        textSleepMin1.setText("" + (sleepData.getTotal() % 60));

                        textDeepHour.setText("" + (sleepData.getDeepValue() / 60));
                        textDeepMin.setText("" + (sleepData.getDeepValue() % 60));
                        textShallowHour.setText("" + (sleepData.getShallowValue() / 60));
                        textShallowMin.setText("" + (sleepData.getShallowValue() % 60));
                        textWlakup.setText("" + sleepData.getWalkingTimes());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }



    private void updateUI() {
        updateTitle();
        updateBg(2);
        SimpleDateFormat sdf;
        switch (dateType) {
            case day:
                sdf = new SimpleDateFormat("MM/dd");
                if (DateFormUtils.isToday(time)) {
                    textDay1.setText(sdf.format(time - DateFormUtils.DAY * 2));
                    textDay2.setText(sdf.format(time - DateFormUtils.DAY));
                    textDay3.setText(R.string.today);
                    updateBg(3);
                } else {
                    textDay1.setText(sdf.format(time - DateFormUtils.DAY));
                    textDay2.setText(sdf.format(time));
                    if (DateFormUtils.isToday(time + DateFormUtils.DAY)) {
                        textDay3.setText(R.string.today);
                    } else {
                        textDay3.setText(sdf.format(time + DateFormUtils.DAY));
                    }
                }
                break;
            case week:
                if (DateFormUtils.isToWeek(time)) {
                    textDay1.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7 * 2));
                    textDay2.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7));
                    textDay3.setText(R.string.toweek);
                    updateBg(3);
                } else {
                    textDay1.setText(DateFormUtils.weekBetwwDesc(time - DateFormUtils.DAY * 7));
                    textDay2.setText(DateFormUtils.weekBetwwDesc(time));
                    if (DateFormUtils.isToWeek(time + DateFormUtils.DAY * 7)) {
                        textDay3.setText(R.string.toweek);
                    } else {
                        textDay3.setText(DateFormUtils.weekBetwwDesc(time + DateFormUtils.DAY * 7));
                    }
                }
                break;
            case month:
                sdf = new SimpleDateFormat("MM月");
                if (DateFormUtils.isToMonth(time)) {
                    sdf = new SimpleDateFormat("MM月");
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -2);
                    textDay1.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    textDay2.setText(sdf.format(calendar.getTime()));
                    textDay3.setText(R.string.tomonth);
                    updateBg(3);
                } else {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(time);
                    calendar.add(Calendar.MONTH, -1);
                    textDay1.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    textDay2.setText(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                    if (DateFormUtils.isToMonth(calendar.getTime().getTime())) {
                        textDay3.setText(R.string.tomonth);
                    } else {
                        textDay3.setText(sdf.format(calendar.getTime()));
                    }
                }
                break;
        }
    }


    private void updateBg(int index) {
        SimpleDateFormat sdf;
        switch (index) {
            case 1:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg_1);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg);

                textDay1.setTextColor(getResources().getColor(R.color.colorText));
                textDay2.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay3.setTextColor(getResources().getColor(R.color.colorWhite));
                break;
            case 2:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg_1);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg);

                textDay1.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay2.setTextColor(getResources().getColor(R.color.colorText));
                textDay3.setTextColor(getResources().getColor(R.color.colorWhite));

                break;
            case 3:
                textDay1.setBackgroundResource(R.drawable.date_btn_bg);
                textDay2.setBackgroundResource(R.drawable.date_btn_bg);
                textDay3.setBackgroundResource(R.drawable.date_btn_bg_1);

                textDay1.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay2.setTextColor(getResources().getColor(R.color.colorWhite));
                textDay3.setTextColor(getResources().getColor(R.color.colorText));

                break;
        }
    }

    private void updateTitle() {
        SimpleDateFormat sdf;
        switch (dateType) {
            case day:
                sdf = new SimpleDateFormat("yyyy/MM/dd");
                textDateTitle.setText(sdf.format(time));
                break;
            case week:
                textDateTitle.setText(DateFormUtils.weekBetwwDescTitle(time));
                break;
            case month:
                sdf = new SimpleDateFormat("MM月");
                textDateTitle.setText(sdf.format(time));
                break;
        }
    }

}
